package com.yunji.framework_template.common.util;

import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javassist.Modifier;

/**
 * 类工具.
 * 
 * @author fenglb
 * @date 2014-3-20 下午7:14:24
 */
public class ClassUtil {

    /**
     * 强行值类型转换.
     * 
     * @param value
     * @param type
     * @return
     * @author yangz
     * @date 2013-2-8 下午5:26:26
     */
    public static Object castValue(Object value, Class<?> type) {
        if (int.class.isAssignableFrom(type) || Integer.class.isAssignableFrom(type)) {
            return ValueUtil.getInt(value);
        } else if (long.class.isAssignableFrom(type) || Long.class.isAssignableFrom(type)) {
            return ValueUtil.getLong(value);
        } else if (double.class.isAssignableFrom(type) || Double.class.isAssignableFrom(type)) {
            return ValueUtil.getDouble(value);
        } else if (boolean.class.isAssignableFrom(type) || Boolean.class.isAssignableFrom(type)) {
            return ValueUtil.getBoolean(value);
        } else if (String.class.isAssignableFrom(type)) {
            return ValueUtil.getString(value);
        } else if (Date.class.isAssignableFrom(type)) {
            return value instanceof Date ? value : DateUtil.parseDate(ValueUtil.getString(value),
                                                                      "yyyy-MM-dd HH:mm:ss");
        } else if (char.class.isAssignableFrom(type) || Character.class.isAssignableFrom(type)) {
            return (char) ValueUtil.getInt(value);
        } else {
            throw new RuntimeException("unknow value type:" + type);
        }
    }

    /**
     * 获取同一路径下所有子类或接口实现类
     * 
     * @param <T>
     * @param intf
     * @return
     * @throws IOException
     * @throws ClassNotFoundException
     */
    @SuppressWarnings("unchecked")
    public static <T> List<Class<T>> getAllAssignedClass(Class<T> cls) throws IOException, ClassNotFoundException {
        List<Class<T>> classes = new ArrayList<Class<T>>();
        for (Class<?> c : getClasses(cls)) {
            // 要查找类的所有非抽象类的子类
            if (cls.isAssignableFrom(c) && !cls.equals(c) && !Modifier.isAbstract(c.getModifiers())) {
                classes.add((Class<T>) c);
            }
        }
        return classes;
    }

    /**
     * 取得当前类路径下的所有类
     * 
     * @param cls
     * @return
     * @throws IOException
     * @throws ClassNotFoundException
     */
    public static List<Class<?>> getClasses(Class<?> cls) throws IOException, ClassNotFoundException {
        String pk = cls.getPackage().getName();
        String path = pk.replace('.', '/');
        ClassLoader classloader = Thread.currentThread().getContextClassLoader();
        URL url = classloader.getResource(path);
        return getClasses(new File(url.getFile()), pk);
    }

    /**
     * 迭代查找类
     * 
     * @param dir
     * @param pk
     * @return
     * @throws ClassNotFoundException
     */
    private static List<Class<?>> getClasses(File dir, String pk) throws ClassNotFoundException {
        List<Class<?>> classes = new ArrayList<Class<?>>();
        if (!dir.exists()) {
            return classes;
        }
        for (File f : dir.listFiles()) {
            if (f.isDirectory()) {
                classes.addAll(getClasses(f, pk + "." + f.getName()));
            }
            String name = f.getName();
            if (name.endsWith(".class")) {
                classes.add(Class.forName(pk + "." + name.substring(0, name.length() - 6)));
            }
        }
        return classes;
    }
}
